/*
 * Copyright 2010-2012 VMware and contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

package cn.wenhao.javaClassReload.classVisitors;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

import cn.wenhao.javaClassReload.testHelper.ClassPrinter;

/**
 * Modifies a class and empties the specified constructors (not a common thing to do!)<br/>
 * 
 * 修改某个字节码对象,将某些特殊描述的构造函数去掉***(不是常见的操作)***.
 * 
 * @author Andy Clement
 * @since 0.8.3
 */
public class EmptyCreator extends ClassVisitor implements Opcodes {

    private String[] descriptors;

    /**
     * Empty the constructors with the specified descriptors.
     * 
     * @param bytesIn input class as bytes
     * @param descriptors descriptors of interest (e.g. "()V")
     * @return modified class as byte array
     */
    public static byte[] invoke(byte[] bytesIn, String...descriptors) {
        ClassReader cr = new ClassReader(bytesIn);
        EmptyCreator ca = new EmptyCreator(descriptors);
        cr.accept(ca, 0);
        byte[] newbytes = ca.getBytes();
        return newbytes;
    }

    private EmptyCreator(String...descriptors) {
        super(ASM4, new ClassWriter(0)); // TODO review 0 here
        this.descriptors = descriptors;
    }

    public byte[] getBytes() {
        byte[] bs = ((ClassWriter) cv).toByteArray();
        ClassPrinter.print(bs);
        return bs;
    }

    private boolean isInterestingDescriptor(String desc) {
        for (int i = 0, max = descriptors.length; i < max; i++) {
            if (descriptors[i].equals(desc)) {
                return true;
            }
        }
        return false;
    }

    public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
        if (name.equals("<init>") && isInterestingDescriptor(desc)) {
            MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
            return new EmptyMethodVisitor(mv);
        } else {
            return super.visitMethod(access, name, desc, signature, exceptions);
        }
    }

}
